<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .error {
        outline: none;
        border-color: red;
      }
      .success {
        outline: none;
        border-color: green;
      }
    </style>
  </head>
  <body>
    <div id="app"></div>
    <template id="t1">
      <div>
        <form id="form">
          <p>
            姓名
            <!-- 数据的双向绑定 -->
            <input
              type="text"
              :value="form.username"
              @input="form.username = $event.target.value;valid('username',$event)"
            />
          </p>
          <p>
            邮箱
            <input
              type="text"
              :value="form.email"
              @input="form.email=$event.target.value;valid('email',$event)"
            />
          </p>
          <p>
            密码
            <input
              type="password"
              :value="form.password"
              @input="form.password=$event.target.value;valid('password',$event)"
            />
          </p>
          <p>
            确认
            <input
              type="password"
              :value="form.cpassword"
              @input="form.cpassword=$event.target.value;valid('cpassword',$event)"
            />
          </p>
          <p>
            <button>提交</button>
          </p>
        </form>
      </div>
    </template>
    <script src="./vue.js"></script>
    <script>
      // 数据驱动视图
      const vm = new Vue({
        el: "#app",
        template: "#t1",
        data: {
          form: {
            // 数据->视图
            username: "jack",
            email: "jack@qq.com",
            password: "",
            cpassword: "",
          },
          rule: {
            cpassword: {
              message: "两次密码输入不一致",
              validator(value) {
                return this.form.password === value;
              },
            },
            password: {
              message: "密码必须3-18位",
              validator(value) {
                return /^.{3,18}$/.test(value);
              },
            },
            username: {
              message: "用户名必须2-18个字符",
              validator(value) {
                return /^\w{2,18}$/.test(value);
              },
            },
            email: {
              message: "邮箱格式错误",
              validator: (value) => {
                return /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
                  value
                );
              },
            },
          },
        },
        methods: {
          valid(name, e) {
            const ruleName = this.rule[name];
            const formName = this.form[name];
            if (ruleName === undefined || formName === undefined) return;
            // 给validator传递输入参数
            const r = ruleName.validator.call(this, formName);

            // 判断相同span节点是否存在，保证同id span只创建一次
            let span = document.getElementById(`err_${name}`);
            if (span === null) {
              // 创建错误提示信息
              span = document.createElement("span");
              span.id = `err_${name}`;
              e.target.after(span);
            }
            if (r === false) {
              span.textContent = ruleName.message;
            } else {
              span.textContent = "";
            }
          },
        },
      });
    </script>
  </body>
</html>
